﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading.Tasks;
using MyMat;
namespace _3Dshower
{
    public class plane
    {
        line[] lines;

        public line[] Lines
        {
            get { return lines; }
        }
        Point[] points;

      
        double[] parameters=new double[3];//z=Ax+By+D 0:A,1:B,2:D
        bool canShow = false;//当C=0时不可显示


        Point centurePoint;
        public Point[] Points
        {
            get { return points; }
        }
        public Point CenturePoint
        {
            get { return centurePoint; }
        }
        public Color color;
        public bool CanShow
        {
            get { return canShow; }
        }
        public Point setBounder(line[] lins, Point centure=null)
        {
            Point[] pos = new Point[4];
            int PoCount = 0;
            for (int i = 0; i < lins.Length; ++i)
            {
                for (int j = 0; j < 2; ++j)
                {
                    int m;
                    for (m = 0; m < PoCount; ++m)
                        if (Object.ReferenceEquals(pos[m], lins[i].Boundary[j]))
                            break;
                    if (m >= PoCount)
                        pos[PoCount++] = lins[i].Boundary[j];
                }
            }
            points = pos;
            lines = lins;
            if (centure == null)
            {
                double x=0,y=0,z=0;
                for (int i=0;i<3;++i)
                {
                    x+=pos[i].Coor[0];
                    y+=pos[i].Coor[1];
                    z+=pos[i].Coor[2];
                }
                centure= new Point(x/3,y/3,z/3);
            }
            centurePoint = centure;
            reCal();
            return centure;
        }
        //计算点是否面内
        private bool isInPlane(Point po)
        {
            if (!canShow)
                return false;
            for (int i = 0; i < lines.Length;++i)
                if (!lines[i].judgeBaseStandard(po))
                    return false;
            return true;            
        }
        //计算面的方程
        public void reCal()
        {
            if (points.Length < 3)
                ;//TODO: 抛出异常
            //开始计算平面方程
            MyVector[] vec = new MyVector[3] { new MyVector(), new MyVector(), new MyVector() };
            //Ax+By+D=z,D需要被计算，当最后一个没有的时候C==0
            vec[0].Date = new double[4] { points[0].Coor[0], points[0].Coor[1], 1, points[0].Coor[2] };
            vec[1].Date = new double[4] { points[1].Coor[0], points[1].Coor[1], 1, points[1].Coor[2] };
            vec[2].Date = new double[4] { points[2].Coor[0], points[2].Coor[1], 1, points[2].Coor[2] };
            MyMatrix m = new MyMatrix() { Date = vec };
            m.Change_Simple();
            
            for (int i = 2; i >= 0; --i)
            {
                int j;
                for (j = 0; j < 3; ++j)
                    if (vec[i].Date[j] == 1)
                    {
                        for (int c = j + 1; c < 3; ++c)
                            if (vec[i].Date[c] != 0)
                            {
                                canShow = false;
                                return;
                            }
                        parameters[j] = vec[i].Date[3];
                        break;
                    }
                if (j == 3 && (vec[i].Date[3]!=0D))
                {
                    canShow = false;
                    return;
                }
            }
            //if (parameters[0] == 0 && parameters[1] == 0)
             //   canShow = false;
           // else
                canShow = true;
            //设置中心标准
            for (int i = 0; i < lines.Length; ++i)
            {
                lines[i].reCal();
                lines[i].setStandard(centurePoint);
            }
            
        }
        //计算点在面里的深度
        public double? pointDeep(Point po)
        {
            //if (!isInPlane(po))//这里不应该注释，就单纯为了立方体实现
            //    return null;
            return parameters[0] * po.Coor[0] + parameters[1] * po.Coor[1]+parameters[2];
        }
        public double? pointDeep(double x,double y)
        {
            Point po = new Point(x, y);
            return pointDeep(po);    
        }

    }
}
